/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.connect5.relations;

import org.jfonia.connect5.basics.BasicValueNode;
import org.jfonia.connect5.basics.MutableValueNode;
import org.jfonia.connect5.basics.Node;
import org.jfonia.connect5.intervals.Interval;
import org.jfonia.connect5.intervals.LinkedIntIntervalList;

/**
 *
 * @author Jannes Plyson
 */
//this relation is best not stored: when merge conditions are met the relation
//will remove itself from all observables and so the garbage collector can collect
//this relation.
public class MergeRelationInt extends MergeRelation{
    

    private Interval<Integer> val1;
    private Interval<Integer> val2;
    private LinkedIntIntervalList list;
    private boolean doSwitchOff;
    private boolean mergeDone;
    public MergeRelationInt(Interval<Integer> val1, Interval<Integer> val2, LinkedIntIntervalList list){        
        this.val1 = val1;
        this.val2 = val2;
        this.list = list;        
        switchOn();
    }

    public void switchOn(){
        doSwitchOff = false;
        mergeDone = false;
        val1.getBeginNode().addObserver(this);
        val1.getEndNode().addObserver(this);
        val2.getBeginNode().addObserver(this);
        val2.getEndNode().addObserver(this);
        enableMerge.addObserver(this);
        merge();
    }

    public void switchOff(){
        val1.getBeginNode().removeObserver(this);
        val1.getEndNode().removeObserver(this);
        val2.getBeginNode().removeObserver(this);
        val2.getEndNode().removeObserver(this);
        enableMerge.removeObserver(this);
    }

    public void merge(){
        if(val1.getEnd().intValue() != val1.getBegin().intValue() && val2.getEnd().intValue() != val2.getBegin().intValue()){
            if(val1.getEnd().intValue() == val2.getBegin().intValue()){
                merge(val1,val2);
            }else if(val2.getEnd().intValue() == val1.getBegin().intValue()){
                merge(val2,val1);
            }
        }
    }

    private void merge(Interval<Integer> firstInterval, Interval<Integer> lastInterval){        
        doSwitchOff = true;
        lastInterval.getBeginNode().setValue(lastInterval.getEnd().intValue());
        if(list.indexOf(lastInterval) != -1){
            list.remove(list.indexOf(lastInterval));
        }
        mergeDone = true;
    }

    public void onNotify(Object source) {
        if(doSwitchOff){
            //this construction is needed because you can't remove a listener from
            //the source
            if(source != val1.getBeginNode() && source != val1.getEndNode()){
                val1.getBeginNode().removeObserver(this);
                val1.getEndNode().removeObserver(this);
            }else if(source != val2.getBeginNode() && source != val2.getEndNode()){
                val2.getBeginNode().removeObserver(this);
                val2.getEndNode().removeObserver(this);
            }
            if(source != enableMerge && mergeDone){
                enableMerge.removeObserver(this);
            }
        }else{
            if(enableMerge.getValue()){
                merge();
            }
        }
    }
}
